#include "hexUtils.h"

string ParseHexString(const string& hexStr)
{
	string::size_type length = hexStr.length();

	if((length & 0x1) != 0)
		return "";

	char* pTemp = (char*)CHexUtils::dehexify(hexStr);

	string str = pTemp;

	str.resize(length >> 1);

	return str;
}

const char CHexUtils::toHexTable[256][2] =
    { 
		{'0','0'}, {'0','1'}, {'0','2'}, {'0','3'}, {'0','4'}, {'0','5'}, {'0','6'}, {'0','7'}, {'0','8'}, {'0','9'}, {'0','A'}, {'0','B'}, {'0','C'}, {'0','D'}, {'0','E'},  {'0','F'},
		{'1','0'}, {'1','1'}, {'1','2'}, {'1','3'}, {'1','4'}, {'1','5'}, {'1','6'}, {'1','7'}, {'1','8'}, {'1','9'}, {'1','A'}, {'1','B'}, {'1','C'}, {'1','D'}, {'1','E'},  {'1','F'},
		{'2','0'}, {'2','1'}, {'2','2'}, {'2','3'}, {'2','4'}, {'2','5'}, {'2','6'}, {'2','7'}, {'2','8'}, {'2','9'}, {'2','A'}, {'2','B'}, {'2','C'}, {'2','D'}, {'2','E'},  {'2','F'},
		{'3','0'}, {'3','1'}, {'3','2'}, {'3','3'}, {'3','4'}, {'3','5'}, {'3','6'}, {'3','7'}, {'3','8'}, {'3','9'}, {'3','A'}, {'3','B'}, {'3','C'}, {'3','D'}, {'3','E'},  {'3','F'},
		{'4','0'}, {'4','1'}, {'4','2'}, {'4','3'}, {'4','4'}, {'4','5'}, {'4','6'}, {'4','7'}, {'4','8'}, {'4','9'}, {'4','A'}, {'4','B'}, {'4','C'}, {'4','D'}, {'4','E'},  {'4','F'},
		{'5','0'}, {'5','1'}, {'5','2'}, {'5','3'}, {'5','4'}, {'5','5'}, {'5','6'}, {'5','7'}, {'5','8'}, {'5','9'}, {'5','A'}, {'5','B'}, {'5','C'}, {'5','D'}, {'5','E'},  {'5','F'},
		{'6','0'}, {'6','1'}, {'6','2'}, {'6','3'}, {'6','4'}, {'6','5'}, {'6','6'}, {'6','7'}, {'6','8'}, {'6','9'}, {'6','A'}, {'6','B'}, {'6','C'}, {'6','D'}, {'6','E'},  {'6','F'},
		{'7','0'}, {'7','1'}, {'7','2'}, {'7','3'}, {'7','4'}, {'7','5'}, {'7','6'}, {'7','7'}, {'7','8'}, {'7','9'}, {'7','A'}, {'7','B'}, {'7','C'}, {'7','D'}, {'7','E'},  {'7','F'},
		{'8','0'}, {'8','1'}, {'8','2'}, {'8','3'}, {'8','4'}, {'8','5'}, {'8','6'}, {'8','7'}, {'8','8'}, {'8','9'}, {'8','A'}, {'8','B'}, {'8','C'}, {'8','D'}, {'8','E'},  {'8','F'},
		{'9','0'}, {'9','1'}, {'9','2'}, {'9','3'}, {'9','4'}, {'9','5'}, {'9','6'}, {'9','7'}, {'9','8'}, {'9','9'}, {'9','A'}, {'9','B'}, {'9','C'}, {'9','D'}, {'9','E'},  {'9','F'},
		{'A','0'}, {'A','1'}, {'A','2'}, {'A','3'}, {'A','4'}, {'A','5'}, {'A','6'}, {'A','7'}, {'A','8'}, {'A','9'}, {'A','A'}, {'A','B'}, {'A','C'}, {'A','D'}, {'A','E'},  {'A','F'},
		{'B','0'}, {'B','1'}, {'B','2'}, {'B','3'}, {'B','4'}, {'B','5'}, {'B','6'}, {'B','7'}, {'B','8'}, {'B','9'}, {'B','A'}, {'B','B'}, {'B','C'}, {'B','D'}, {'B','E'},  {'B','F'},
		{'C','0'}, {'C','1'}, {'C','2'}, {'C','3'}, {'C','4'}, {'C','5'}, {'C','6'}, {'C','7'}, {'C','8'}, {'C','9'}, {'C','A'}, {'C','B'}, {'C','C'}, {'C','D'}, {'C','E'},  {'C','F'},
		{'D','0'}, {'D','1'}, {'D','2'}, {'D','3'}, {'D','4'}, {'D','5'}, {'D','6'}, {'D','7'}, {'D','8'}, {'D','9'}, {'D','A'}, {'D','B'}, {'D','C'}, {'D','D'}, {'D','E'},  {'D','F'},
		{'E','0'}, {'E','1'}, {'E','2'}, {'E','3'}, {'E','4'}, {'E','5'}, {'E','6'}, {'E','7'}, {'E','8'}, {'E','9'}, {'E','A'}, {'E','B'}, {'E','C'}, {'E','D'}, {'E','E'},  {'E','F'},
		{'F','0'}, {'F','1'}, {'F','2'}, {'F','3'}, {'F','4'}, {'F','5'}, {'F','6'}, {'F','7'}, {'F','8'}, {'F','9'}, {'F','A'}, {'F','B'}, {'F','C'}, {'F','D'}, {'F','E'},  {'F','F'},
	
	};

string CHexUtils::hexify(const unsigned char *data, unsigned int length)
{
	string hexified;
	hexified.resize(length * 2);

	char *h = &hexified[0];
	const unsigned char *dataEnd = data + length;

	for(const unsigned char *c = data; c != dataEnd; ++c, h += 2)
	{
		h[0] = toHexTable[*c][0];
		h[1] = toHexTable[*c][1];
	}

	return hexified;
}

unsigned char *CHexUtils::dehexify(const unsigned char *data, unsigned int length)
{
	const unsigned char *dataEnd = data + length;

	unsigned int lengthRes = length >> 1;
	unsigned char *res = SAFE_NEW unsigned char[lengthRes];
	memset(res, 0, lengthRes);

	int i = 0;
	for(const unsigned char *c = data; c != dataEnd; c+=2, ++i)
	{
		int v0 = getHexDigitVal(c[0]);
		int v1 = getHexDigitVal(c[1]);
		
		res[i] = (v0 << 4) | v1;
	}

	return res;
}

unsigned char *CHexUtils::dehexify(const string &hexified)
{
	const char *h = &hexified[0];
	const char *hEnd = h + hexified.length();

	unsigned int lengthRes = hexified.length() >> 1;
	unsigned char *res = SAFE_NEW unsigned char[lengthRes];
	memset(res, 0, lengthRes);

	int i = 0;
	for(const char *c = h; c != hEnd; c+=2, ++i)
	{
		int v0 = getHexDigitVal(c[0]);
		int v1 = getHexDigitVal(c[1]);
		
		res[i] = (v0 << 4) | v1;
	}

	return res;
}

int CHexUtils::getHexDigitVal(const char c)
{
	// c is a digit from '0' to '9'
	if(c >= 48 && c <= 57)
	{
		return c - 48;
	}
	// c is an uppercase letter from 'A' to 'F'
	else if(c >= 65 && c <= 70)
	{
		// result = c - 65 + 10
		return c - 55;
	}
	else if(c >= 97 && c <= 102)
	{
		// result = c - 97 + 10
		return c - 87;
	}

	return -1;
}